import { Injectable, inject } from '@angular/core';
import { TreeNode } from 'primeng/api';
import { v4 as uuid } from 'uuid';
import { g } from './global-data'
import { TransformService } from '@/home/service/transform.service';
import { TrackLineService } from './track-line.service';
import { DataSaveService } from './data-save.service';
import { TrackLine } from '../data-model/track-line.model';
import { WayPoint } from '../data-model/way-point.model';

@Injectable({
    providedIn: 'root'
})
export class GpxParserService {
    transformService = inject(TransformService);
    trackLineService = inject(TrackLineService);
    dataSaveService = inject(DataSaveService);

    parse_gpx(gpx_string: string, file_name: string): any {
        try {
            const parser = new DOMParser();
            const xml_document = parser.parseFromString(gpx_string, "text/xml");

            // 检查是否为有效的XML文件
            if (xml_document.getElementsByTagName("parsererror").length > 0) {
                throw new Error("无效的XML文件格式");
            }

            const gpx = xml_document.childNodes[0];
            if (gpx.nodeName !== 'gpx') {
                throw new Error("无效的KML文件格式");
            }

            const gpx_root: TreeNode = {
                type: 'folder',
                label: '未命名',
                expanded: true,
                children: [],
            };
            const wpt_folder: TreeNode = {
                type: 'folder',
                label: '路点',
                expanded: false,
                children: [],
            }
            gpx_root.children?.push(wpt_folder);

            for (const child of gpx.childNodes) {
                const tag = child.nodeName.toLowerCase();
                if (tag === 'name') {
                    gpx_root.label = child.textContent || '未命名';
                } else if (tag === 'metadata') {
                    for (const sub_child of child.childNodes) {
                        const sub_tag = sub_child.nodeName.toLowerCase();
                        if (sub_tag === 'name') {
                            gpx_root.label = sub_child.textContent!;
                        }
                    }
                } else if (tag === 'wpt') {
                    // 一个文件夹下最多添加100个路点（以及轨迹等节点），多余的忽略
                    if (wpt_folder.children!.length < 100) {
                        const way_point = this.parse_gpx_wpt(child);
                        wpt_folder.children!.push(way_point);                        
                    }

                } else if (tag === 'trk') {
                    let track_name = file_name;
                    for (const sub_child of child.childNodes) {
                        const sub_tag = sub_child.nodeName.toLowerCase();
                        if (sub_tag === 'name') {
                            track_name = sub_child.textContent!;
                        } else if (sub_tag === 'trkseg') {
                            const track_line = this.parse_trkseg(sub_child, track_name);
                            gpx_root.children!.push(track_line);
                        }
                    }
                }
            }

            if (wpt_folder.children!.length === 0) {
                gpx_root.children!.splice(0, 1);
            }

            if (wpt_folder.children!.length === 1) {
                gpx_root.children!.splice(0, 1);
                gpx_root.children!.push(wpt_folder.children![0]);
            }

            if (gpx_root.children!.length === 0) {
                return [];
            }

            if (gpx_root.children!.length === 1) {
                return [ gpx_root.children![0] ];
            }

            return [ gpx_root ];

        } catch (error) {
            console.error('解析KML文件失败:', error);
            return [];
        }
    }

    parse_gpx_wpt(wpt_node: any) {
        const way_point: WayPoint = {
            type: 'way_point',
            label: '未命名',
            uuid: uuid().replace(/-/g, '').toLowerCase(),
            pin_index: 0,
            visible: false,
        }

        const attributes: NamedNodeMap = wpt_node.attributes;
        way_point.lon = parseFloat(attributes.getNamedItem('lon')!.value);
        way_point.lat = parseFloat(attributes.getNamedItem('lat')!.value);
        way_point.alt = 0;
        for (const child of wpt_node.childNodes) {
            const tag = child.nodeName.toLowerCase();
            if (tag === 'name') {
                way_point.label = child.textContent || '未命名';
            } else if (tag === 'ele') {
                way_point.alt = parseFloat(child.textContent);
            } else if (tag === 'time') {
                way_point.timestamp = child.textContent;
            }
        }

        way_point.fpx = this.transformService.get_fpx_from_longitude(way_point.lon);
        way_point.fpy = this.transformService.get_fpy_from_latitude(way_point.lat);

        // 路点与轨迹共用一个渲染缓存
        if (way_point.visible) {
            g.visible_tracks.set(way_point.uuid, way_point);
            g.tracks_to_be_drawn.push(way_point);
        }

        return way_point;
    }

    parse_trkseg(trkseg: any, name: string) {
        const track_line: TrackLine = {
            type: 'track_line',
            label: name,
            uuid: uuid().replace(/-/g, '').toLowerCase(),
            width: 2,
            red: 0,
            green: 0,
            blue: 255,
            alpha: 255,
            draw_endpoints: true,
            visible: true,
            has_timestamp: false,
        }

        const track_line_points = [];
        for (const trkpt of trkseg.childNodes) {
            const tag = trkpt.nodeName.toLowerCase();
            if (tag === 'trkpt') {
                const attributes: NamedNodeMap = trkpt.attributes;
                const lon = parseFloat(attributes.getNamedItem('lon')!.value);
                const lat = parseFloat(attributes.getNamedItem('lat')!.value);
                let alt = 0;
                let timestamp = '';
                for (const child of trkpt.childNodes) {
                    const tag1 = child.nodeName.toLowerCase();
                    if (tag1 === 'ele') {
                        alt = parseFloat(child.textContent);
                    } else if (tag1 === 'time') {
                        timestamp = child.textContent;
                        track_line.has_timestamp = true;
                    }
                }

                const track_point = [
                    lon,
                    lat,
                    alt,
                    timestamp,
                    this.transformService.get_fpx_from_longitude(lon),
                    this.transformService.get_fpy_from_latitude(lat)
                ];
                track_line_points.push(track_point);
            }
        }

        g.track_line_points_cache.set(track_line.uuid, track_line_points);
        this.dataSaveService.save_track_data(track_line.uuid!);

        this.trackLineService.compute_track_line_args(track_line);

        if (track_line.visible) {
            g.visible_tracks.set(track_line.uuid, track_line);
            g.tracks_to_be_drawn.push(track_line);
        }

        return track_line;
    }

}
